package com.minli.weixin.service.imp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.minli.weixin.common.util.BsStringUtil;
import com.minli.weixin.common.util.HttpUtils;
import com.minli.weixin.common.util.JedisUtils;
import com.minli.weixin.common.util.entity.HttpResp;
import com.minli.weixin.service.IWxmpService;
import com.minli.weixin.service.bo.WxUserInfo;
import com.minli.weixin.service.bo.WxmpTempMsg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class WxmpServiceImpl implements IWxmpService {
	private Logger logger = LoggerFactory.getLogger(WxmpServiceImpl.class);
	 /** 微信获取access_token*/
    private final String API_ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

    /** 微信获取用户资料*/
    private final String API_ACCESS_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";

    /** jsapi 获取token*/
    private final String JS_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";

    /** jsapi 获取ticket*/
    private final String JS_GET_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi";

    /** jsapi 签名*/
    private final String JS_SIGN = "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s";

	/**	微信发送消息*/
	private static final String API_NOTICE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
    
    @Value("${wxmp.appId}")
    private String appId;

    @Value("${wxmp.appSecret}")
    private String appSecret;

    @Value("${wxmp.version}")
    private String version;

	/**	access_token 缓存键值*/
    private static final String CACHE_ACCESS_TOKEN = "WXMP_ACCESS_TOKEN";
	/**	access_token 缓存超时时间，单位秒，公众平台为2小时超时，提前10秒超时*/
    private static final int CACHE_ACCESS_TOKEN_TIMEOUT = 7190;

	@Override
    public String getAccessToken(boolean refresh) {
		refresh = true;
    	String accessToken = null;
    	if(!refresh){
    		accessToken = JedisUtils.get(CACHE_ACCESS_TOKEN);
    	}
    	if(StringUtils.isEmpty(accessToken)){
    		String mm = String.format(JS_ACCESS_TOKEN, appId, appSecret);
	        String tokenHttpResp = reqHttp(String.format(JS_ACCESS_TOKEN, appId, appSecret));
	        logger.info("获取access_token,微信返回="+tokenHttpResp);
	        String token = JSON.parseObject(tokenHttpResp).getString("access_token");
	        JedisUtils.set(CACHE_ACCESS_TOKEN, token);
	        JedisUtils.setex(CACHE_ACCESS_TOKEN, CACHE_ACCESS_TOKEN_TIMEOUT, token);
	        return token;
    	}
    	return accessToken;
    }
	
	@Override
	public String sendTempMsg(WxmpTempMsg wxmpTempMsg) throws Exception {
		logger.info("接收到通知内容="+wxmpTempMsg);
		
    	JSONObject outJson = new JSONObject();
    	outJson.put("touser", wxmpTempMsg.getOpenId());
    	outJson.put("template_id", wxmpTempMsg.getTemplateId());
    	outJson.put("url",wxmpTempMsg.getUrl());
    	outJson.put("data", wxmpTempMsg.getData());
		
    	String requestUrl = String.format(API_NOTICE_URL,getAccessToken(false));
        String rst = HttpUtils.getInstance().httpRequest(requestUrl, "POST", outJson.toJSONString());
        logger.info("微信通知消息返回="+rst);
        
        //如果access_token 失效，则重新取一次
        //token过期微信返回 {"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest hint: [_y9phA0928sz10!]"}
        if(!StringUtils.isEmpty(rst) && BsStringUtil.isJson(rst)){
        	JSONObject rstJson = JSON.parseObject(rst);
        	if("40001".equals(rstJson.getString("errcode"))){
        		String requestUrl2 = String.format(API_NOTICE_URL,getAccessToken(true));
                String rst2 = HttpUtils.getInstance().httpRequest(requestUrl2, "POST", outJson.toJSONString());
                logger.info("微信通知消息返回2="+rst2);
        	}
        }
		return null;
	}
	
	@Override
	public JSONObject getAccessInfo(String code) throws Exception {
		String mm = String.format(API_ACCESS_TOKEN, appId, appSecret, code);
        String resp = reqHttp(String.format(API_ACCESS_TOKEN, appId, appSecret, code));
        JSONObject respJSON = JSON.parseObject(resp);
        String openid = respJSON.getString("openid");
        if (StringUtils.isEmpty(openid)){
            throw new Exception("微信授权获取openId失败");
        }
        return respJSON;
    }

	@Override
    public WxUserInfo getUserInfo(String access_token, String openid) throws Exception {
        String respInfo = reqHttp(String.format(API_ACCESS_INFO,access_token,openid));
        JSONObject respJsonInfo = JSON.parseObject(respInfo);
        String nickName = respJsonInfo.getString("nickname");
        if (StringUtils.isEmpty(nickName)){
            throw new Exception("微信授权获取openId失败");
        }
        return JSON.parseObject(respInfo,WxUserInfo.class);
    }
    
	@Override
	public String getJsapiTicket() {
        String access_token = getAccessToken(false);
        String tickHttpResp = reqHttp(String.format(JS_GET_TICKET, access_token));
        return JSON.parseObject(tickHttpResp).getString("ticket");
	}
	
    /**
     * http请求
     * @param url
     * @return
     */
    private String reqHttp(String url) {
        HttpResp httpResp = HttpUtils.getInstance().get(url);
        return httpResp.getBodyString();
    }

	@Override
	public String getJsSign() {
		return JS_SIGN;
	}

	@Override
	public String getVersion() {
		return version;
	}

	@Override
	public String getAppId() {
		return appId;
	}
}
